C++ Quick Reference
File Types: .h and .cpp Files
In C++, code is typically organized into two types of files:
What are Header Files (.h)
Header files contain declarations - they tell the compiler what functions, classes, and variables exist, but not how they work.
Think of a header file like a table of contents or menu at a restaurant - it lists what's available but doesn't contain the full recipe or instructions.
Why do we need header files?
- They let other parts of your program know what functions and classes are available to use
- They act like a "promise" - telling the compiler "these things exist, trust me"
- They allow you to organize your code into separate files
What goes in .h files:
- Include statements (
#include
) - Bringing in other header files that this file needs - Function declarations (what the function looks like) - Just the name, what it takes in, and what it gives back
- Class definitions (what properties and methods a class has) - The blueprint of the class
- Variable declarations - Telling the compiler a variable exists somewhere
- Constants and definitions - Fixed values that won't change
Example - Drivetrain.h:
#pragma once
#include <frc/xrp/XRPMotor.h>
#include <frc2/command/SubsystemBase.h>
class Drivetrain : public frc2::SubsystemBase {
public:
Drivetrain();
// A function to drive the robot with tank-style controls.
// It takes a speed for the left side and a speed for the right side.
void TankDrive(double leftSpeed, double rightSpeed);
/**
* Will be called periodically whenever the CommandScheduler runs.
*/
void Periodic() override;
private:
// Components (e.g. motor controllers and sensors) should generally be
// declared private and exposed only through public methods.
// This creates an object for the left motor on channel 0
frc::XRPMotor m_left_motor{0};
// This creates an object for the right motor on channel 1
frc::XRPMotor m_right_motor{1};
};
What are Source Files (.cpp)
Source files contain definitions - they contain the actual code that does the work.
Think of a source file like the full recipe with step-by-step instructions, or like the actual kitchen where the cooking happens.
Why do we need source files?
- They contain the "meat" of your program - the actual working code
- They implement the promises made in the header files
- They do the real work when your program runs
What goes in .cpp files:
- Function implementations (the actual code that runs) - The detailed steps of what the function does
- The detailed code for class methods - How each function in a class actually works
- The main program logic - The code that gets executed when you run your program
- Include statements - Bringing in the header files so you can use what's declared there
Example - Drivetrain.cpp:
#include "subsystems/Drivetrain.h"
Drivetrain::Drivetrain() = default;
// This is the definition of our TankDrive function.
// The code inside the curly braces {} is what runs when we call this function.
void Drivetrain::TankDrive(double leftSpeed, double rightSpeed) {
// This line tells our left motor object to set its speed to the value of leftSpeed.
m_left_motor.Set(leftSpeed);
// This line does the same for the right motor, using the rightSpeed value.
m_right_motor.Set(-rightSpeed);
}
// This method will be called once per scheduler run
void Drivetrain::Periodic() {}
Simple Rule of Thumb:
- .h file: "What can this code do?" (the interface/promise)
- Like a job description - it tells you what skills someone has
- .cpp file: "How does this code actually work?" (the implementation/actual work)
- Like watching someone actually do the job
Include Statements (#include
)
In C++, #include
statements are used to bring in code from other files or libraries. This allows you to use functions, classes, and variables that are defined elsewhere.
Why use #include
?
- To use code from the C++ Standard Library (like
#include <iostream>
for input/output) - To use your own code from other files (like
#include "Drivetrain.h"
) - To use code from external libraries (like WPILib for FRC)
Syntax
#include <filename> // For standard or external libraries
#include "filename" // For your own files in the project
Tip:
- Use angle brackets
< >
for system or library headers. - Use double quotes
" "
for your own project files.
Member Variable Declarations
Member variables (also called fields or member objects) are variables that are declared inside a class. They represent the data or components that each object (instance) of the class will have.
Why use member variables?
- To store information or state for each object
- To represent hardware components (like motors or controllers) in robot code
- To keep related data and functions together in a class
Example:
class RobotContainer {
public:
RobotContainer();
private:
Drivetrain m_drivetrain; // Subsystem member variable
frc::XboxController m_controller{0}; // Input device member variable
};
Tip:
- The
m_
prefix is a common convention to indicate a member variable. - Member variables can be objects (like
Drivetrain
orfrc::XboxController
) or basic types (likeint
).
Flow Charts
Flow charts are visual representations of the flow of a program. They use symbols to represent different types of actions or steps in a process.
Common Flowchart Shapes:
-
🟩 Rectangle (Box): Represents an action or process step
- Example: "Set motor speed" or "Calculate result"
- This is where your program does something
-
💎 Diamond: Represents a decision or question
- Example: "Is age >= 18?" or "Is button pressed?"
- This is where your program decides what to do next
- Always has "Yes/No" or "True/False" arrows coming out
-
🟢 Circle/Oval: Represents start or end points
- "Start" - where your program begins
- "End" - where your program finishes
-
➡️ Arrows: Show the direction of flow
- Tell you which step comes next
- From diamonds, they're labeled with the decision result (Yes/No)
Example: Consider a program that checks if a person is old enough to vote (age 18 or older).
Variables and Data Types
Variables are used to store data in your program. In C++, you must declare a variable with a specific data type.
Common Data Types:
int
: Stores integers (e.g.,42
,-7
).double
: Stores floating-point numbers (e.g.,3.14
,-0.01
).char
: Stores a single character (e.g.,'A'
,'z'
).bool
: Storestrue
orfalse
.std::string
: Stores text (requires#include <string>
).
Example:
int age = 25;
double pi = 3.14159;
char grade = 'A';
bool isStudent = true;
std::string name = "John";
Control Structures
Control structures allow you to control the flow of your program.
If-Else Statements
Think of an if-else
statement as a way for your program to make decisions. It's like asking a series of questions. The computer checks each question in order and runs the code for the first one that is true.
if
: Asks the first question.else if
: If the first answer was "no," ask a second question.else
: If all the answers were "no," do this as a default.
This structure is perfect for choosing one action from several options.
Syntax:
if (condition1) {
// Code to execute if condition1 is true
} else if (condition2) {
// Code to execute if condition2 is true
} else {
// Code to execute if none of the conditions are true
}
Example:
int age = 20;
if (age < 13) {
std::cout << "You are a child.\n";
} else if (age < 18) {
std::cout << "You are a teenager.\n";
} else {
std::cout << "You are an adult.\n";
}
In this example:
- If
age
is less than 13, the program prints "You are a child." - If
age
is between 13 and 17, the program prints "You are a teenager." - Otherwise, the program prints "You are an adult."
For Loop
The for
loop is used to repeat a block of code a specific number of times. It consists of three parts:
- Initialization: Sets the starting value of a variable.
- Condition: Checks if the loop should continue.
- Increment/Decrement: Updates the variable after each iteration.
Syntax:
for (initialization; condition; increment/decrement) {
// Code to execute in each iteration
}
Example:
for (int i = 0; i < 5; i++) {
std::cout << i << "\n"; // Prints numbers from 0 to 4
}
While Loop
The while
loop repeats a block of code as long as a condition is true
. The condition is checked before each iteration.
Syntax:
while (condition) {
// Code to execute while condition is true
}
Example:
int i = 0;
while (i < 5) {
std::cout << i << "\n"; // Prints numbers from 0 to 4
i++; // Increments i by 1
}
Switch (Case) Statement
The switch
statement is used to execute one block of code out of many options based on the value of a variable. It is often used as an alternative to multiple if-else
statements.
Syntax:
switch (variable) {
case value1:
// Code to execute if variable == value1
break;
case value2:
// Code to execute if variable == value2
break;
// Add more cases as needed
default:
// Code to execute if none of the cases match
break;
}
Example:
int day = 3;
switch (day) {
case 1:
std::cout << "Monday\n";
break;
case 2:
std::cout << "Tuesday\n";
break;
case 3:
std::cout << "Wednesday\n";
break;
default:
std::cout << "Invalid day\n";
break;
}
In this example, the program checks the value of day
. If day
is 3
, it prints "Wednesday". If no cases match, the default
block runs.
Functions
Functions are reusable blocks of code that perform a specific task.
In C++, functions are usually declared in a header (.h
) file and defined in a source (.cpp
) file.
-
Declaration: Tells the compiler that a function exists and what its signature is (name, return type, parameters), but not what it does.
-
Definition: Provides the actual code (body) for the function.
Example:
Drivetrain.h (Declaration):
// Declaration (in header file)
void TankDrive(double leftSpeed, double rightSpeed);
Drivetrain.cpp (Definition):
// Definition (in source file)
void Drivetrain::TankDrive(double leftSpeed, double rightSpeed) {
m_left_motor.Set(leftSpeed);
m_right_motor.Set(-rightSpeed);
}
Input and Output
C++ uses std::cin
for input and std::cout
for output.
What are std::cin
and std::cout
?
std::cout
: This is used to print output to the console. Think of it as a way to "talk" to the user by displaying messages or values.std::cin
: This is used to take input from the user. Think of it as a way to "listen" to what the user types.
Note: std::cin
is not typically used in FRC programming because robot code does not interact with users via the console. Instead, inputs are usually taken from controllers or sensors.
Example:
#include <iostream>
int main() {
int age;
std::cout << "Enter your age: "; // Ask the user for their age
std::cin >> age; // Read the user's input and store it in the variable 'age'
std::cout << "You are " << age << " years old.\n"; // Print the user's age
return 0;
}
In this example:
std::cout
displays the message "Enter your age: ".std::cin
waits for the user to type a number and stores it in theage
variable.std::cout
then prints the message "You are [age] years old.".
Arrays and Vectors
Arrays
Fixed-size collections of elements of the same type.
int numbers[5] = {1, 2, 3, 4, 5};
std::cout << numbers[0]; // Access the first element
Vectors
Dynamic-size collections (requires #include <vector>
).
#include <vector>
std::vector<int> numbers = {1, 2, 3};
numbers.push_back(4); // Add an element
std::cout << numbers[0]; // Access the first element
Classes and Objects
C++ is an object-oriented language. Classes are blueprints for creating objects.
Example:
class Car {
public:
std::string brand;
int speed;
void drive() {
std::cout << "Driving at " << speed << " mph.\n";
}
};
Car myCar;
myCar.brand = "Toyota";
myCar.speed = 60;
myCar.drive();
Pointers
Pointers store the address of a variable, not the variable itself. Think of it like a house address - it tells you where to find something.
Basic Syntax
int number = 42;
int* ptr = &number; // ptr stores the address of number
std::cout << ptr; // Prints the address (e.g., 0x7fff...)
std::cout << *ptr; // Prints 42 (goes to address and gets the value)
Key Operators
&
= Get the address of a variable*
= Get the value at an address->
= Call methods through a pointer
Common FRC Usage
// Pass subsystem to command
DriveCommand(Drivetrain* drivetrain) : m_drivetrain(drivetrain) {}
// Use the subsystem
void Execute() {
m_drivetrain->ArcadeDrive(0.5, 0.0); // Use -> for pointers
}
Quick Rules
- Use
&variable
to get an address - Use
*pointer
to get the value at that address - Use
pointer->method()
to call methods - Don't use
nullptr
pointers (will crash!)
Comments
Comments are ignored by the compiler and are used to explain code.
- Single-line comment:
//
- Multi-line comment:
/* */
Example:
// This is a single-line comment
/*
This is a
multi-line comment
*/
Error Handling
Use try
and catch
blocks to handle exceptions.
Example:
try {
int x = 10 / 0; // Division by zero
} catch (std::exception& e) {
std::cout << "Error: " << e.what() << "\n";
}
Namespaces
Namespaces in C++ are used to organize code and prevent naming conflicts. They group related classes, functions, and variables under a unique name.
- Avoid Naming Conflicts: If two libraries define a function or variable with the same name, namespaces ensure they don't clash.
- Organize Code: Group related functionality together for better readability.
Part 1: Defining Values
In this part, we define constants inside a namespace.
// RobotConfig.h
#pragma once
```cpp
namespace DrivetrainConstants {
constexpr static double kMoveSpeed = 0.75; // Speed for moving forward and backward (1 = max speed, 0 = stopped)
constexpr static double kTurnSpeed = 0.5; // Speed for turning left and right (1 = max speed, 0 = stopped)
}
namespace DrivetrainConstants
: This creates a container or a "scope" namedDrivetrainConstants
. It's used to group related variables together to keep the code organized and to avoid naming conflicts.constexpr
: This keyword declares the variable as a "constant expression." It means its value is fixed and must be known when the code is compiled.static
: This keyword limits the variable's visibility to just this file. It helps prevent conflicts if another file were to accidentally declare a variable with the same name.double
: This is the data type, which means the variable can hold a number with a decimal point. This is suitable for representing speeds that aren't whole numbers.kMoveSpeed
: This is the name of the variable. Thek
prefix is a common programming convention (especially in FRC) to indicate that the variable is a constant.
Part 2: Reading and Using Values
In this part, we access the values from the namespace and use them in calculations.
// main.cpp
#include "RobotConfig.h" // Include the namespace file
int main() {
// Access the variables using the namespace
double current_speed = DrivetrainConstants::kMoveSpeed;
double current_turning_speed = DrivetrainConstants::kTurnSpeed;
return 0;
}